import socket, traceback, os, sys, struct
from threading import *
from qcrc16 import *
import qutils

class HTCPServer(object):
    HTCP_SERVER_TYPE_NONE 		= 0x00
    HTCP_SERVER_TYPE_WATER 		= 0x07
    HTCP_SERVER_TYPE_AMMETER 	= 0x08
    HTCP_SERVER_TYPE_MAX 		= 0xFF

    def __init__(self, aAddr):
        self.srvType 	= HTCPServer.HTCP_SERVER_TYPE_NONE
        self.addrSrv 	= aAddr
        self.serverdict = {}

    # FIXME, a server registered 2 times  and runtime register is not implement
    def registerServer(self, server):
        st = server.srvType
        if st > HTCPServer.HTCP_SERVER_TYPE_NONE and st < HTCPServer.HTCP_SERVER_TYPE_MAX:
            self.serverdict[st]= server

    def sendResponse(self, aSocket, action, response):
        htcpbuf = struct.pack('!4sBBB', "HTCP", self.srvType, action, len(response))
        htcpbuf += struct.pack('!%dsBB' % (len(response)), response, 0, 0)
        try:
        	qutils.htprint("REQ", htcpbuf)
        	aSocket.send(htcpbuf)
        	return 0
    	except Exception, e:
        	print e
        	print 'sendResponse except'
        return -1

    def sendCommand(self, sock, action, data):
    	tmpLen = len(data)
    	if tmpLen > 0 :
        	htcpbuf = struct.pack('!4sBBB', "HTCP", self.srvType, action, len(data))
        	htcpbuf += struct.pack('!%dsBB' % (len(data)), data, 0, 0)
        else :
        	htcpbuf = struct.pack('!4sBBBBB', "HTCP", self.srvType, action, 0, 0, 0)
        #htcparray = qcrc16.createarray(bytearray(htcpbuf))
        try:
        	qutils.htprint("REQ", htcpbuf)
        	sock.send(htcpbuf)
        	return 0
    	except Exception, e:
        	print e
        	print 'sendCommand except'
        return -1
        
    def handleCommand(self, aSocket, action, request):
        pass

    def handleEvent(self, aSocket, action, request):
        pass
    
    def __handleThread(self, aSocket):
        print "="*50
        print "Got connection from", aSocket.getpeername()

        while True:
            try:
                recvBuf = aSocket.recv(512)
            except:
                aSocket.close()
                print "recv exception!"
                return

            if not len(recvBuf):
                print aSocket,"closed"
                aSocket.close()
                return

            qutils.htprint("RSP", recvBuf)
            if len(recvBuf) < 7 or recvBuf.find('HTCP') < 0:
                aSocket.close()
                return
            	
            tmpCmds = recvBuf.split('HTCP')
            for tmpCmd in tmpCmds :
            	if len(tmpCmd) < 9 :
            		continue
            	server, action, datalen = struct.unpack("!BBB", tmpCmd[0:3])
                if len(tmpCmd) < (datalen + 3) :
                    continue
            	if self.serverdict.has_key(server):
	            	req, = struct.unpack("!%ds" % (datalen), tmpCmd[3:3+datalen])
	            	currserver = self.serverdict[server]
	            	if action < 0x80:
	                	currserver.handleCommand(aSocket, action, req)
	            	else:
	                	currserver.handleEvent(aSocket, action, req)

    def loop(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(self.addrSrv)
        s.listen(1)
        while True:
            try:
                clientsock, clientaddr = s.accept()
                print s
            except KeyboardInterrupt:
                break
            except:
                print "except"
                traceback.print_exc()
                continue

            t = Thread(target=self.__handleThread, args = [clientsock])
            t.setDaemon(1)
            t.start()
